package lxs.swift.tool;


import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;


public class Dater {
    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    public static final String MONTH_PATTERN = "yyyy-MM";
    public static final String YEAR_PATTERN = "yyyy";
    public static final String TIME_PATTERN = "HH:mm:ss";

    public final Date date;
    private final Calendar calendar;

    private Dater(Date date) {
        this.date = date;
        this.calendar = Calendar.getInstance();
        this.calendar.setTime(date);
    }

    private Dater(Date date, int field, int amount) {
        this.calendar = Calendar.getInstance();
        this.calendar.setTime(date);
        this.calendar.add(field, amount);
        this.date = this.calendar.getTime();
    }

    public static Dater of(Date date) {
        return new Dater(date);
    }

    public static Dater parse(String s) {
        String patten = "";
        if (s.length() >= DATE_PATTERN.length()) patten = DATE_TIME_PATTERN;
        else if (s.length() <= YEAR_PATTERN.length()) patten = YEAR_PATTERN;
        else if (s.length() <= MONTH_PATTERN.length()) patten = MONTH_PATTERN;
        else {
            if (s.indexOf("-") != 0) patten = DATE_PATTERN;
            else patten = TIME_PATTERN;
        }
        return parse(s, patten);
    }


    public static Dater parse(String s, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        ParsePosition position = new ParsePosition(0);
        return new Dater(simpleDateFormat.parse(s, position));
    }


    public static Dater parseDate(String s) {
        return parse(s, DATE_PATTERN);
    }

    public static Dater parseMonth(String s) {
        return parse(s, MONTH_PATTERN);
    }

    public static Dater parseYear(String s) {
        return parse(s, YEAR_PATTERN);
    }

    public static Dater parseTime(String s) {
        return parse(s, TIME_PATTERN);
    }


    public String formatDatetime() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_TIME_PATTERN);
        return simpleDateFormat.format(date);
    }

    public String formatMonth() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(MONTH_PATTERN);
        return simpleDateFormat.format(date);
    }

    public String formatYear() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(YEAR_PATTERN);
        return simpleDateFormat.format(date);
    }

    public String formatDate() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_PATTERN);
        return simpleDateFormat.format(date);
    }

    public String formatTime() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(TIME_PATTERN);
        return simpleDateFormat.format(date);
    }

    public String format(String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return simpleDateFormat.format(date);
    }


    public int year() {
        return calendar.get(Calendar.YEAR);
    }

    public int month() {
        return calendar.get(Calendar.MONTH);
    }

    public int day() {
        return calendar.get(Calendar.DATE);
    }

    public int hour() {
        return calendar.get(Calendar.HOUR);
    }

    public int minute() {
        return calendar.get(Calendar.MINUTE);
    }

    public int second() {
        return calendar.get(Calendar.SECOND);
    }

    public int weekOfYear() {
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

    public int weekOfMonth() {
        return calendar.get(Calendar.WEEK_OF_MONTH);
    }

    public Dater firstDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(this.date);
        // 获取当月最小天数
        int firstDay = calendar.getActualMinimum(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, firstDay);
        return new Dater(calendar.getTime());
    }

    public Dater lastDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(this.date);
        // 获取当月最大天数
        int lastDay;
        //2月的平年瑞年天数
        if (this.month() == 2) {
            lastDay = calendar.getLeastMaximum(Calendar.DAY_OF_MONTH);
        } else {
            lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        }
        // 设置日历中月份的最大天数
        calendar.set(Calendar.DAY_OF_MONTH, lastDay);
        return new Dater(calendar.getTime());
    }

    public Dater retainYear() {
        int year = this.year();
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        return new Dater(calendar.getTime());
    }

    public Dater retainMonth() {
        int year = this.year();
        int month = this.month();
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        return new Dater(calendar.getTime());
    }

    public Dater retainDate() {
        int year = this.year();
        int month = this.month();
        int day = this.day();
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DATE, day);
        return new Dater(calendar.getTime());
    }

    public Dater retainHour() {
        int year = this.year();
        int month = this.month();
        int day = this.day();
        int hour = this.hour();
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DATE, day);
        calendar.set(Calendar.HOUR, hour);
        return new Dater(calendar.getTime());
    }

    public Dater retainMinute() {
        int year = this.year();
        int month = this.month();
        int day = this.day();
        int hour = this.hour();
        int minute = this.minute();
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DATE, day);
        calendar.set(Calendar.HOUR, hour);
        calendar.set(Calendar.MINUTE, minute);
        return new Dater(calendar.getTime());
    }


    public Dater addDays(int amount) {
        return new Dater(this.date, Calendar.DATE, amount);
    }

    public Dater addSeconds(int amount) {
        return new Dater(this.date, Calendar.SECOND, amount);
    }

    public Dater addMinutes(int amount) {
        return new Dater(this.date, Calendar.MINUTE, amount);
    }

    public Dater addHours(int amount) {
        return new Dater(this.date, Calendar.HOUR, amount);
    }

    public Dater addMonths(int amount) {
        return new Dater(this.date, Calendar.MONTH, amount);
    }

    public Dater addYears(int amount) {
        return new Dater(this.date, Calendar.YEAR, amount);
    }

    public static boolean gt(String left, String right, boolean equal) {
        Date leftDate = Dater.parse(left).date;
        Date rightDate = Dater.parse(right).date;
        int compare = leftDate.compareTo(rightDate);
        if (compare == 0) return equal;
        return compare > 0;
    }

    public static boolean lt(String left, String right, boolean equal) {
        Date leftDate = Dater.parse(left).date;
        Date rightDate = Dater.parse(right).date;
        int compare = leftDate.compareTo(rightDate);
        if (compare == 0) return equal;
        return compare < 0;
    }

    /**
     * 获取起始日期到结束日期加1之间的所有日期
     *
     * @param startDate 起始日期
     * @param endDate   结束日期
     * @return 起始日期到结束日期之间的所有日期
     */
    public static List<String> dateList(String startDate, String endDate) {
        if (startDate.contains(" ")) startDate = startDate.substring(0, startDate.indexOf(' '));
        if (endDate.contains(" ")) endDate = endDate.substring(0, endDate.indexOf(' '));
        Date s = parse(startDate, DATE_PATTERN).date;
        Date e = parse(endDate, DATE_PATTERN).date;
        return dateList(s, e);
    }

    public static List<String> dateList(Date startDate, Date endDate) {
        return timeList(startDate, endDate, "day", DATE_TIME_PATTERN);
    }

    public static List<String> timeList(Date startDate, Date endDate, String unit, String PATTERN) {
        if (startDate.getTime() > endDate.getTime()) {
            Date date = startDate;
            startDate = endDate;
            endDate = date;
        }
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00"));
        calendar.setTime(startDate);
        List<String> re = new ArrayList<>();
        re.add(Dater.of(startDate).format(PATTERN));

        while (calendar.getTime().compareTo(endDate) < 0) {
            switch (unit) {
                case "minute":
                    calendar.add(Calendar.MINUTE, 1);
                    break;
                case "hour":
                    calendar.add(Calendar.HOUR, 1);
                    break;
                case "day":
                    calendar.add(Calendar.DATE, 1);
                    break;
                case "week":
                    calendar.add(Calendar.DATE, 7);
                    break;
                case "month":
                    calendar.add(Calendar.MONTH, 1);
                    break;
                case "season":
                    calendar.add(Calendar.MONTH, 3);
                    break;
                case "year":
                    calendar.add(Calendar.YEAR, 1);
                    break;
            }
            re.add(Dater.of(calendar.getTime()).format(PATTERN));
        }
        return re;
    }

    public static Date getLastDay(String month) {
        String[] split = month.split("-");
        int yearNum = Integer.parseInt(split[0]);  //年
        int monthNum = Integer.parseInt(split[1]); //月
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, yearNum);
        cal.set(Calendar.MONTH, monthNum); //设置当前月的上一个月
        int lastDay = cal.getMinimum(Calendar.DATE); //获取月份中的最小值,即第一天
        cal.set(Calendar.DAY_OF_MONTH, lastDay - 1); //上月的第一天减去1就是当月的最后一天
        return cal.getTime();
    }

}
